데이터
데이터는 오마이뉴스 GitHub에서 가져옵니다.
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.2 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.2 ✔ tibble 3.2.1
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Linking to GEOS 3.11.2, GDAL 3.6.2, PROJ 9.2.0; sf_use_s2() is TRUE
map_sf <- sf:: st_read ("data/2020_21_elec_253_simple.json" )
Reading layer `2020_21_elec_253_simple' from data source
`C:\Users\mimi\Documents\openai\data\2020_21_elec_253_simple.json'
using driver `GeoJSON'
Simple feature collection with 253 features and 4 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 124.6098 ymin: 33.16123 xmax: 130.9175 ymax: 38.61369
Geodetic CRS: WGS 84
st_geometry (map_sf) |> plot ()
st_drop_geometry (map_sf) |> as_tibble ()
# A tibble: 253 × 4
SGG_Code SGG_1 SGG_2 SGG_3
<int> <chr> <chr> <chr>
1 2270202 대구 대구광역시 동구을 대구 동구을
2 2270101 대구 대구광역시 중구남구 대구 중구남구
3 2412001 경기 경기도 고양시갑 경기 고양갑
4 2411002 경기 경기도 안양시동안구을 경기 안양동안을
5 2480802 경남 경상남도 김해시을 경남 김해을
6 2410301 경기 경기도 수원시병 경기 수원병
7 2280702 인천 인천광역시 계양구을 인천 계양을
8 2110601 서울 서울특별시 동대문구갑 서울 동대문갑
9 2460702 전남 전라남도 순천시광양시곡성군구례군을 전남 순천광양곡성구례을
10 2440103 충남 충청남도 천안시병 충남 천안병
# ℹ 243 more rows
후보 데이터
Attaching package: 'rvest'
The following object is masked from 'package:readr':
guess_encoding
wiki_url <- "https://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD_%EC%A0%9C21%EB%8C%80_%EA%B5%AD%ED%9A%8C%EC%9D%98%EC%9B%90_%EC%84%A0%EA%B1%B0_%EB%8D%94%EB%B6%88%EC%96%B4%EB%AF%BC%EC%A3%BC%EB%8B%B9_%ED%9B%84%EB%B3%B4_%EB%AA%A9%EB%A1%9D"
sido_name <- read_html (wiki_url) |>
html_nodes ("h3" ) |>
html_text () |>
str_remove (" \\ [편집 \\ ]" )
minju_lst <- read_html (wiki_url) |>
html_nodes (".wikitable" ) |>
html_table ()
names (minju_lst) <- sido_name
nomination <- sido_name |>
enframe (value = "시도명" ) |>
mutate (data = minju_lst) |>
unnest (data) |>
select (- name) |>
janitor:: clean_names (ascii = FALSE )
nomination |>
slice_sample (n = 10 ) |>
select (- 경력) |>
gt:: gt ()
시도명
선거구
후보자
공천_유형
유튜브
인천광역시
중·강화·옹진
조택상
단수 공천
https://www.youtube.com/channel/UC4iL-5zH6AEXRRs5nLjE4cQ
서울특별시
동작 을
이수진
전략 공천
https://www.youtube.com/channel/UC9jenXiV9fP7wy122SbkmQA
경기도
안산 단원 갑
고영인
경선 공천
https://www.youtube.com/channel/UCaaIRghu-ZjqIdKe0-ZbShA
부산광역시
남 갑
강준석
전략 공천
https://www.youtube.com/channel/UC5-U8m3qTMMVRQexUXTBIVA
인천광역시
연수 갑
박찬대
단수 공천
https://www.youtube.com/channel/UCM2tZCsO6uDgbUxtG2WBkww
경상남도
사천·남해·하동
황인성
단수 공천
https://www.youtube.com/channel/UCyWyvV_Www3Xlx_qYhe7eKQ
서울특별시
강서 을
진성준
단수 공천
https://www.youtube.com/channel/UCzWEju7x5X_6-rR4eFJnZqw
서울특별시
마포 을
정청래
단수 공천
https://www.youtube.com/channel/UCGrKYDAbwFSUnee4Z50yEhw
대구광역시
달서 병
김대진
단수 공천
https://www.youtube.com/channel/UCQdfhg1w9b36JcaJ00p-C2Q
충청남도
아산 을
강훈식
단수 공천
https://www.youtube.com/channel/UCMKz8kR5MUN-uHB2_Jy_swg
nomination |>
write_rds ("data/nomination.rds" )
# write_rds("data/nomination.csv")->크롤링 웹사이트 로컬에 저장
출판
요약표
library (tidyverse)
library (gt)
library (gtExtras)
nomination <- read_rds ("data/nomination.rds" )
nomi_table <- nomination |>
count (공천_유형, name = "선거구수" ) |>
arrange (desc (선거구수)) |>
mutate (비율 = 선거구수 / sum (선거구수)) |>
janitor:: adorn_totals (name = "합계" )
nomi_gt <- nomi_table |>
gt () |>
gt_theme_538 () |>
cols_align (align = "center" ) |>
fmt_percent (columns = 비율, decimals = 1 ) |>
tab_options (
heading.title.font.size = px (18L),
column_labels.font.size = px (14L),
table.font.size = px (11L)
) |>
tab_header (
title = md ("더불어민주당 공천 유형" ),
subtitle = md ("제21대 국회의원 선거" )
) |>
tab_style (
style = cell_fill (color = "pink" ),
locations = cells_body (
rows = 공천_유형 == "단수 공천"
)
) |>
tab_style (
style = cell_text ("red" ),
locations = cells_body (
rows = 공천_유형 == "단수 공천" ,
columns = 비율
)
)
nomi_gt |> gt:: gtsave (filename = "data/nomi_gt.png" )
library (ggrepel)
extrafont:: loadfonts ()
precinct_nomination_tbl <-
readxl:: read_excel ("data/precinct_nomination.xlsx" )
precinct <- st_read ("data/2020_21_elec_253_simple.json" ) |>
st_set_crs (4326 )
precinct_nomination_sf <-
left_join (precinct |> select (SGG_Code, geometry),
precinct_nomination_tbl,
by = "SGG_Code" )
st_geometry (precinct_nomination_sf) |> plot ()
nomination_type_gg <- ggplot () +
geom_sf (data = precinct_nomination_sf,
aes (geometry = geometry, fill = 공천_유형)) +
theme_void (base_family = "MaruBuri" ) +
theme (legend.position = "left" ) +
scale_fill_manual (values = c ("경선 공천" = "gray90" ,
"단수 공천" = "red" ,
"전략 공천" = "pink" ,
"청년 경선 공천" = "black" )) +
labs (title = "대한민국 제21대 국회의원 선거 더불어민주당 후보" ,
caption = "자료출처: 위키백과" )
metro_bb <- precinct_nomination_sf |>
filter (SGG_1 == "경기" ) |> st_bbox ()
metro_nomination_type_gg <- ggplot () +
geom_sf (data = precinct_nomination_sf |> filter (SGG_1 %in% c ("서울" , "경기" )),
aes (geometry = geometry, fill = 공천_유형)) +
theme_void (base_family = "MaruBuri" ) +
coord_sf (xlim = c (metro_bb['xmin' ], metro_bb['xmax' ]),
ylim = c (metro_bb['ymin' ], metro_bb['ymax' ]), expand = FALSE ) +
theme (legend.position = "none" ) +
scale_fill_manual (values = c ("경선 공천" = "gray90" ,
"단수 공천" = "red" ,
"전략 공천" = "pink" ,
"청년 경선 공천" = "black" )) +
ggrepel:: geom_text_repel (
data = precinct_nomination_sf |> filter (SGG_1 %in% c ("서울" , "경기" )) |>
mutate (SGG_3 = glue:: glue ("{ifelse(str_detect(공천_유형,'단수'), SGG_3, '')}" )),
aes (label = SGG_3, geometry = geometry), stat = "sf_coordinates" ,
min.segment.length = 1 , size = 4 , max.overlaps = Inf
)
library (patchwork)# 그래프를 합쳐주는 패키지
nomination_type_final <- nomination_type_gg + metro_nomination_type_gg +
plot_layout (widths = c (1 , 2 ))#차트 크기 조정
nomination_type_final
ggplot2:: ggsave ("data/two_map.png" )
ragg:: agg_jpeg ("data/two_map.jpg" ,
width = 10 , height = 7 , units = "in" , res = 600 )
nomination_type_final
dev.off ()